﻿using Adnc.Application.Shared.Dtos;
using Adnc.Application.Shared.Enum;
using Adnc.Application.Shared.Services;
using Adnc.Infra.Helper;
using Adnc.Infra.IRepositories;
using Adnc.Shared.Consts;
using Adnc.Shared.RpcServices.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
using WYT.Pro.Application.Contracts.Dtos.Product;
using WYT.Pro.Application.Contracts.Services;
using WYT.Pro.Repository.Entites;

namespace WYT.Pro.Application.Services
{
    /// <summary>
    /// 商品服务
    /// </summary>
    public class ProductAppService : AbstractAppService, IProductAppService
    {
        private readonly IEfRepository<GoodsPrice> _goodsPriceRepository;

        private readonly IEfRepository<Goods> _goodsRepository;

        private readonly IEfRepository<GoodsGroups> _goodsGroupRepository;

        private readonly IEfRepository<GoodsGroupDetails> _groupGoodsRepository;

        private readonly IEfRepository<GoodsSize> _goodsSizeRepository;

        private readonly IEfRepository<GoodsReview> _goodsReviewRepository;

        private readonly IEfRepository<GoodsReviewReply> _goodsReviewReplyRepository;

        private readonly IEfRepository<GoodsGift> _goodsGiftRepository;

        private readonly IUserRpcService _userRpcService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="goodsPriceRepository"></param>
        /// <param name="goodsRepository"></param>
        /// <param name="goodsGroupRepository"></param>
        /// <param name="groupGoodsRepository"></param>
        /// <param name="goodsSizeRepository"></param>
        /// <param name="goodsReviewRepository"></param>
        /// <param name="goodsReviewReplyRepository"></param>
        /// <param name="goodsGiftRepository"></param>
        /// <param name="userRpcService"></param>
        public ProductAppService(
                    IEfRepository<GoodsPrice> goodsPriceRepository,
                    IEfRepository<Goods> goodsRepository,
                    IEfRepository<GoodsGroups> goodsGroupRepository,
                    IEfRepository<GoodsGroupDetails> groupGoodsRepository,
                    IEfRepository<GoodsSize> goodsSizeRepository,
                    IEfRepository<GoodsReview> goodsReviewRepository,
                    IEfRepository<GoodsReviewReply> goodsReviewReplyRepository,
                    IEfRepository<GoodsGift> goodsGiftRepository,
                    IUserRpcService userRpcService
            )
        {
            _goodsRepository = goodsRepository;
            _goodsPriceRepository = goodsPriceRepository;
            _goodsGroupRepository = goodsGroupRepository;
            _groupGoodsRepository = groupGoodsRepository;
            _userRpcService = userRpcService;
            _goodsSizeRepository = goodsSizeRepository;
            _goodsGiftRepository = goodsGiftRepository;
            _goodsReviewRepository = goodsReviewRepository;
            _goodsReviewReplyRepository = goodsReviewReplyRepository;
        }

        /// <summary>
        /// 获取商品详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<ProductDetailDto>> GetProductDetailById(ProductSearchDto input)
        {
            bool isZh = input.Language.Equals(LanguageConsts.ZH);
            var userGradeResponse = await _userRpcService.GetUserGrade();
            if (!userGradeResponse.IsSuccessStatusCode)
                return Problem(HttpStatusCode.BadRequest, "服务异常");
            var grade = userGradeResponse.Content;

            var goods = await _goodsRepository.FindAsync(input.GoodsId);
            if (goods == null)
                return Problem(HttpStatusCode.NotFound, "找不到商品");

            var sizes = await _goodsSizeRepository.Where(x => x.GoodsID == input.GoodsId && x.State == 0).ToListAsync();
            var sizeIds = sizes.Select(x => x.Id).ToList();
            var prices = await _goodsPriceRepository.Where(c => sizeIds.Contains(c.SizeID)).ToListAsync();
            var gifts = await _goodsGiftRepository.Where(x => sizeIds.Contains(x.ParentGoodsSizeId) && x.IsDelete == false && x.RemainderCount > 0).ToListAsync();
            var giftGoodsIds = gifts.Select(x => x.GoodsId).ToList();
            var giftGoodsSizeIds = gifts.Select(x => x.SizeId).ToList();

            var giftGoods = await _goodsRepository.Where(x => giftGoodsIds.Contains(x.Id)).ToListAsync();
            var giftGoodsSize = await _goodsSizeRepository.Where(x => giftGoodsSizeIds.Contains(x.Id)).ToListAsync();

            ProductDetailDto productDetail = new ProductDetailDto
            {
                Id = input.GoodsId,
                Name = isZh ? goods.Name : goods.UighurName,
                Slogan = JsonSerializer.Deserialize<string[]>(isZh ? goods.Slogan: goods.UighurSlogan),
                Tag =  JsonSerializer.Deserialize<string[]>(isZh ? goods.Tag : goods.UighurTag),
                Banner = JsonSerializer.Deserialize<string[]>(isZh ? goods.Banner : goods.UighurBanner),
                Details = JsonSerializer.Deserialize<string[]>(isZh ? goods.Details : goods.UighurDetails),
                IsThirdParties = goods.IsThirdParties,
                IsForeign = goods.IsForeign,
                Shareable = goods.Shareable,
                Sales = goods.Sales,
                VideoAddress = JsonSerializer.Deserialize<string[]>(isZh ? goods.VideoAddress : goods.UighurVideoAddress)
            };

            List<ProductSizeDto> sizelist = new List<ProductSizeDto>();
            foreach (var item in sizes)
            {
                var price = prices.First(c => c.SizeID == item.Id && c.UserLevel == grade);
                var gift = gifts.FindAll(x => x.ParentGoodsSizeId == item.Id);
                var dto = new ProductSizeDto()
                {
                    SizeID = item.Id,
                    IsDefalut = item.IsDefalut,
                    SizeName = isZh ? item.Name : item.UighurName,
                    Thumbnail = item.Thumbnail,
                    ProxyIntegral = item.ProxyIntegral,
                    CurrentPrice = price.Price,
                    OriginalPrice = item.Price,
                    Inventory = item.Inventory,
                    PriceDiff = goods.IsThirdCoupons ? item.ThirdCommission : Decimal.Subtract(item.Price, price.Price),

                };
                if (gift.Count > 0)
                    dto.Gift = gift.Select(x => {
                        var gs = giftGoodsSize.First(c => c.Id == x.SizeId);
                        var g = giftGoods.First(c => c.Id == gs.GoodsID);
                        return new ProductGiftDto()
                        {
                            SizeId = x.SizeId,
                            GoodsId = x.GoodsId,
                            BuyCount = x.BuyCount,
                            Count = x.Count,
                            IsSuperposition = x.IsSuperposition,
                            SizeName = isZh ? gs.Name : gs.UighurName,
                            GoodsName = isZh ? g.Name : g.UighurName
                        };
                    }).ToList();
                sizelist.Add(dto);
            }

            productDetail.Size = sizelist;

            var reviewCount = await _goodsReviewRepository.CountAsync(c => c.GoodsId == input.GoodsId);
            var firstReview = _goodsReviewRepository.Where(c => c.GoodsId == input.GoodsId).OrderByDescending(c => c.CreateTime).FirstOrDefault();

            productDetail.ProductReviewCount = reviewCount;
            if (firstReview != null)
            {
                var userInfors = await _userRpcService.GetUserNameAndHead(new long[] { firstReview.UserId });
                if (userInfors.IsSuccessStatusCode)
                {
                    var re = userInfors.Content.FirstOrDefault();
                    ProductReviewListDto productReview = new ProductReviewListDto
                    {
                        Id = firstReview.Id,
                        UserName = SensitiveHelper.GetSensitiveData(re.Name),
                        HeadUrl = re.Head,
                        Content = firstReview.Content,
                        Video = JsonSerializer.Deserialize<string[]>(firstReview.Video),
                        Image = JsonSerializer.Deserialize<string[]>(firstReview.Image),
                        CommentTime = TimeHelper.GetTimeSpanStr(firstReview.CreateTime)
                    };
                    productDetail.ProductReview = productReview;
                }
            }

            return productDetail;
        }

        /// <summary>
        /// 根据规格ID获取商品规格详情
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="hasGift">是否返回赠品信息</param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<ProductSizeWithGiftDetailDto>>> GetProductSizeDetailById(long[] ids, bool hasGift = false)
        {
            var sizes = await _goodsSizeRepository.Where(c => ids.Contains(c.Id)).ToListAsync();
            var goodIds = sizes.Select(c => c.GoodsID).Distinct().ToList();
            var goods = await _goodsRepository.Where(c => goodIds.Contains(c.Id)).ToListAsync();
            var prics = await _goodsPriceRepository.Where(c => ids.Contains(c.SizeID)).ToListAsync();

            List<ProductSizeWithGiftDetailDto> result = new List<ProductSizeWithGiftDetailDto>();

            foreach (var size in sizes)
            {
                var good = goods.Find(c => c.Id == size.GoodsID);
                var priceList = prics.FindAll(c => c.SizeID == size.Id).Select(c => new ProductPriceDto()
                {
                    Price = c.Price,
                    UserLevel = c.UserLevel,
                    IntegralPrice = c.IntegralPrice
                }).ToList();
                result.Add(new ProductSizeWithGiftDetailDto()
                {
                    GoodsID = good.Id,
                    GoodsName = good.Name,
                    Code = good.Code,
                    Slogan = good.Slogan,
                    Tag = good.Tag,
                    UighurGoodsName = good.UighurName,
                    UighurSlogan = good.UighurSlogan,
                    UighurTag = good.UighurTag,
                    IsThirdParties = good.IsThirdParties,
                    ERPEnable = good.ERPEnable,
                    IsForeign = good.IsForeign,
                    GoodsType = good.GoodsType,
                    SurfacePlot = good.SurfacePlot,
                    Banner = good.Banner,
                    Details = good.Details,
                    VideoAddress = good.VideoAddress,
                    UighurSurfacePlot = good.UighurSurfacePlot,
                    UighurBanner = good.UighurBanner,
                    UighurDetails = good.UighurDetails,
                    UighurVideoAddress = good.UighurVideoAddress,
                    NotSellAreaCode = good.NotSellAreaCode,
                    CreateTime = good.CreateTime,
                    PutawayTime = good.PutawayTime,
                    OffLoadingTime = good.OffLoadingTime,
                    IsSendRepertory = good.IsSendRepertory,
                    SizeID = size.Id,
                    ERPCode = size.ERPCode,
                    SizeName = size.Name,
                    UighurSizeName = size.UighurName,
                    Thumbnail = size.Thumbnail,
                    PerformancePrice = size.PerformancePrice,
                    CostPrice = size.CostPrice,
                    Price = size.Price,
                    ProxyIntegral = size.ProxyIntegral,
                    ShoppingIntegral = size.ShoppingIntegral,
                    WarGoods = size.WarGoods,                     
                    WarSize = size.WarSize,
                    WarCount = size.WarCount,
                    ProductPrices = priceList,
                    LogisticsId = good.LogisticsId,
                    Inventory = size.Inventory,
                    TraceSource = good.TraceSource,
                    IsThirdCoupons = good.IsThirdCoupons,
                    SupplierId = good.SupplierId,
                    ThirdCommission = size.ThirdCommission,
                });
            }

            if (hasGift)
            {
                //赠品信息
                var gifts = await _goodsGiftRepository.Where(x => ids.Contains(x.ParentGoodsSizeId) && x.IsDelete == false && x.RemainderCount > 0).ToListAsync();
                if (gifts.Any())
                {
                    var giftGoodsIds = gifts.Select(x => x.GoodsId).ToList();
                    var giftGoodsSizeIds = gifts.Select(x => x.SizeId).ToList();
                    var giftGoods = _goodsRepository.Where(x => giftGoodsIds.Contains(x.Id)).ToList();
                    var giftGoodsSize = _goodsSizeRepository.Where(x => giftGoodsSizeIds.Contains(x.Id)).ToList();

                    foreach(var item in result)
                    {
                        item.Gift = gifts.FindAll(x => x.ParentGoodsSizeId == item.SizeID).Select(x => {
                            var size = giftGoodsSize.First(c => c.Id == x.SizeId);
                            var goods = giftGoods.First(c => c.Id == size.GoodsID);
                            return new ProductGiftDto()
                            {
                                Id = x.Id,
                                SizeId = x.SizeId,
                                GoodsId = x.GoodsId,
                                BuyCount = x.BuyCount,
                                Count = x.Count,
                                RemainderCount = x.RemainderCount,
                                IsSuperposition = x.IsSuperposition,
                                GiftDetail = new ProductSizeDetailDto {
                                    GoodsID = goods.Id,
                                    GoodsName = goods.Name,
                                    Code = goods.Code,
                                    Slogan = goods.Slogan,
                                    Tag = goods.Tag,
                                    UighurGoodsName = goods.UighurName,
                                    UighurSlogan = goods.UighurSlogan,
                                    UighurTag = goods.UighurTag,
                                    IsThirdParties = goods.IsThirdParties,
                                    ERPEnable = goods.ERPEnable,
                                    IsForeign = goods.IsForeign,
                                    GoodsType = goods.GoodsType,
                                    SurfacePlot = goods.SurfacePlot,
                                    Banner = goods.Banner,
                                    Details = goods.Details,
                                    VideoAddress = goods.VideoAddress,
                                    UighurSurfacePlot = goods.UighurSurfacePlot,
                                    UighurBanner = goods.UighurBanner,
                                    UighurDetails = goods.UighurDetails,
                                    UighurVideoAddress = goods.UighurVideoAddress,
                                    NotSellAreaCode = goods.NotSellAreaCode,
                                    CreateTime = goods.CreateTime,
                                    PutawayTime = goods.PutawayTime,
                                    OffLoadingTime = goods.OffLoadingTime,
                                    IsSendRepertory = goods.IsSendRepertory,
                                    SizeID = size.Id,
                                    ERPCode = size.ERPCode,
                                    SizeName = size.Name,
                                    UighurSizeName = size.UighurName,
                                    Thumbnail = size.Thumbnail,
                                    PerformancePrice = size.PerformancePrice,
                                    CostPrice = size.CostPrice,
                                    Price = size.Price,
                                    ProxyIntegral = size.ProxyIntegral,
                                    ShoppingIntegral = size.ShoppingIntegral,
                                    WarGoods = size.WarGoods,
                                    WarSize = size.WarSize,
                                    WarCount = size.WarCount,
                                    LogisticsId = goods.LogisticsId,
                                    Inventory = size.Inventory,
                                    TraceSource = goods.TraceSource,
                                    IsThirdCoupons = goods.IsThirdCoupons,
                                    ThirdCommission = size.ThirdCommission,
                                    SupplierId = goods.SupplierId,
                                }
                            };
                        }).ToList();                        
                    }
                }                
            }
            return result;
        }


        /// <summary>
        /// 获取所有云仓规格详情
        /// </summary>
        /// <returns></returns>
        public async Task<AppSrvResult<List<ProductSizeSimpleInforDto>>> GetAllWarehouseProduct()
        {
            var goods = await _goodsRepository.Where(c => c.IsSendRepertory == true && c.State == 0).ToListAsync();
            var goodIds = goods.Select(c => c.Id).ToList();
            var sizes = await _goodsSizeRepository.Where(x => goodIds.Contains(x.GoodsID) && x.State == 0).ToListAsync();          
            
            var result = new List<ProductSizeSimpleInforDto>();
            foreach (var item in sizes)
            {
                var g = goods.First(x => x.Id == item.GoodsID);
                result.Add(new ProductSizeSimpleInforDto()
                {
                    GoodsId = g.Id,
                    GoodsName = g.Name,
                    UighurGoodsName = g.UighurName,
                    GoodsType = g.GoodsType,
                    SizeId = item.Id,
                    SizeName = item.Name,
                    UighurSizeName = item.UighurName,
                    SurfacePlot = g.SurfacePlot,
                    UighurSurfacePlot = g.UighurSurfacePlot
                });
            }
            return result;
        }

        /// <summary>
        /// 获取商品简单信息
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<ProductSizeSimpleInforDto>>> GetProductSizeSimpleInforById(long[] ids)
        {
            var goodsSizes = await _goodsSizeRepository.Where(x => ids.Contains(x.Id)).ToListAsync();
            var goodsId = goodsSizes.Select(x => x.GoodsID).ToArray();
            var goods = await _goodsRepository.Where(x => goodsId.Contains(x.Id)).ToListAsync();
            var result = new List<ProductSizeSimpleInforDto>();
            foreach (var item in goodsSizes)
            {
                var g = goods.First(x => x.Id == item.GoodsID);
                result.Add(new ProductSizeSimpleInforDto() { 
                    GoodsId = g.Id,
                    GoodsName = g.Name,
                    UighurGoodsName = g.UighurName,
                    GoodsType = g.GoodsType,
                    SizeId = item.Id,
                    SizeName = item.Name,
                    UighurSizeName = item.UighurName,
                    SurfacePlot = g.SurfacePlot,
                    UighurSurfacePlot = g.UighurSurfacePlot
                });
            }
            return result;
        }

        /// <summary>
        /// 获取云仓商品列表
        /// </summary>
        /// <param name="Language"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<ProductListDto>>> GetWarProductList(string Language)
        {
            bool isZh = Language.Equals(LanguageConsts.ZH);
            //获取用户等级
            var userGradeResponse = await _userRpcService.GetUserGrade();
            if (!userGradeResponse.IsSuccessStatusCode)
                return Problem(HttpStatusCode.InternalServerError, "服务异常");
            var usergrade = userGradeResponse.Content;

            List<ProductListDto> warProductList = new List<ProductListDto>();
            var warGoods = await _goodsRepository.Where(c => c.IsSendRepertory == true && c.State == 0).ToListAsync();
            var goodsIds = warGoods.Select(c => c.Id).ToList();
            var warSizes = await _goodsSizeRepository.Where(c => goodsIds.Contains(c.GoodsID) && c.State == 0).ToListAsync();
            var sizeIds = warSizes.Select(x => x.Id).ToList();
            var prices = await _goodsPriceRepository.Where(c => sizeIds.Contains(c.SizeID)).ToListAsync();

            foreach (var size in warSizes)
            {
                var goods = warGoods.FirstOrDefault(c => c.Id == size.GoodsID);
                if (goods == null)
                    continue;
                var product = new ProductListDto
                {
                    Id = goods.Id,
                    Name = isZh ? goods.Name : goods.UighurName,
                    OriginalPrice = size.Price,
                    SizeId = size.Id,
                    SurfacePlot = isZh ? goods.SurfacePlot : goods.UighurSurfacePlot,
                    Tag = isZh ? goods.Tag.Split(",") : goods.UighurTag.Split(","),
                    IsThirdParties = goods.IsThirdParties,
                    IsForeign = goods.IsForeign,
                    CurrentPrice = prices.FindAll(c =>c.SizeID == size.Id).FirstOrDefault(c => c.UserLevel == usergrade).Price
                };
                product.PriceDiff = product.OriginalPrice - product.CurrentPrice;
                warProductList.Add(product);
            }

            return warProductList;
        }

        /// <summary>
        /// 查询商品
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<ProductListDto>>> ProductSearch(SimpleSearchDto<string> input)
        {
            bool isZh = input.Language.Equals(LanguageConsts.ZH);
            //获取用户等级
            var userGradeResponse = await _userRpcService.GetUserGrade();
            if (!userGradeResponse.IsSuccessStatusCode)
                return Problem(HttpStatusCode.InternalServerError, "服务异常");
            var usergrade = userGradeResponse.Content;

            List<ProductListDto> list = new List<ProductListDto>();

            var expres = ExpressionCreator.New<Goods>()
                .AndIf(isZh, x => x.Name.Contains(input.Value))
                .AndIf(!isZh, x => x.UighurName.Contains(input.Value))
                .And(x => x.PutawayTime == null || x.PutawayTime <= DateTime.Now)
                .And(x => x.OffLoadingTime == null || x.OffLoadingTime >= DateTime.Now)
                .And(x => x.GoodsType != (int)EnumGoodsType.GOODS_TYPE_UNSHOW)
                .And(x => x.State == 0);

            var goods = _goodsRepository.Where(expres).ToList();
            var goodsIds = goods.Select(c => c.Id).ToList();
            if (goodsIds.Count > 0)
            {
                var sizes = _goodsSizeRepository.Where(c => goodsIds.Contains(c.GoodsID) && c.State == 0).ToList();
                var sizeIds = sizes.Select(c => c.Id).ToList();
                var prices = _goodsPriceRepository.Where(x => sizeIds.Contains(x.SizeID)).ToList();

                foreach (var item in goods)
                {
                    var size = sizes.FindAll(x => x.GoodsID == item.Id).OrderBy(x => x.Id).FirstOrDefault();
                    if (size != null)
                    {
                        var price = prices.Find(x => x.SizeID == size.Id && x.UserLevel == usergrade);
                        list.Add(new ProductListDto { 
                            Id = item.Id,
                            SizeId = size.Id,
                            Name = isZh ? item.Name : item.UighurName,
                            IsThirdParties = item.IsThirdParties,
                            IsForeign = item.IsForeign,
                            SurfacePlot = isZh ? item.SurfacePlot : item.UighurSurfacePlot,
                            OriginalPrice = size.Price,
                            CurrentPrice = price.Price,
                            PriceDiff = item.IsThirdCoupons ? size.ThirdCommission : size.Price - price.Price,
                            Tag = JsonSerializer.Deserialize<String[]>(isZh ? item.Tag : item.UighurTag)
                        });
                    }
                }
            }

            return list;
        }

        /// <summary>
        /// 获取周边产品
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<ProductListDto>>> GetPeripheralProducts(SearchDto input)
        {
            bool isZh = input.Language.Equals(LanguageConsts.ZH);
            //获取用户等级
            var userGradeResponse = await _userRpcService.GetUserGrade();
            if (!userGradeResponse.IsSuccessStatusCode)
                return Problem(HttpStatusCode.InternalServerError, "服务异常");
            var usergrade = userGradeResponse.Content;

            List<ProductListDto> list = new List<ProductListDto>();

            var expres = ExpressionCreator.New<Goods>()
                .And(x => x.GoodsType == (int)EnumGoodsType.GOODS_TYPE_PERIPHERY)
                .And(x => x.PutawayTime == null || x.PutawayTime <= DateTime.Now)
                .And(x => x.OffLoadingTime == null ||  x.OffLoadingTime >= DateTime.Now)
                .And(x => x.State == 0);

            var goods = _goodsRepository.Where(expres).ToList();
            var goodsIds = goods.Select(c => c.Id).ToList();
            if (goodsIds.Count > 0)
            {
                var sizes = _goodsSizeRepository.Where(c => goodsIds.Contains(c.GoodsID) && c.State == 0 && c.IsDefalut == true).ToList();
                var sizeIds = sizes.Select(c => c.Id).ToList();
                var prices = _goodsPriceRepository.Where(x => sizeIds.Contains(x.SizeID)).ToList();

                foreach (var item in goods)
                {
                    var size = sizes.FirstOrDefault(x => x.GoodsID == item.Id);
                    if (size != null)
                    {
                        var price = prices.Find(x => x.SizeID == size.Id && x.UserLevel == usergrade);
                        list.Add(new ProductListDto
                        {
                            Id = item.Id,
                            SizeId = size.Id,
                            Name = isZh ? item.Name : item.UighurName,
                            IsThirdParties = item.IsThirdParties,
                            IsForeign = item.IsForeign,
                            SurfacePlot = isZh ? item.SurfacePlot : item.UighurSurfacePlot,
                            OriginalPrice = size.Price,
                            CurrentPrice = price.Price,
                            PriceDiff = item.IsThirdCoupons ? size.ThirdCommission : size.Price - price.Price,
                            Tag = JsonSerializer.Deserialize<String[]>(isZh ? item.Tag : item.UighurTag)
                        });
                    }
                }
            }

            return list;
        }

        /// <summary>
        /// 改变商品数量
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult> ChangeProductNum(ProductNumChangeDto input)
        {
            if (input.Product.Count() > 0)
            {
                var sizeIds = input.Product.Select(x => x.Id).ToList();
                var goodsSize = await _goodsSizeRepository.Where(x => sizeIds.Contains(x.Id)).ToListAsync();
                var goodsIds = goodsSize.Select(x => x.GoodsID);
                var goods = await _goodsRepository.Where(x => goodsIds.Contains(x.Id)).ToListAsync();
                foreach (var item in input.Product)
                {
                    var size = goodsSize.Find(x => x.Id == item.Id);
                    var g = goods.Find(x => x.Id == size.GoodsID);
                    if (input.Type == 1)
                    {
                        size.Inventory -= item.Num;
                        g.Sales += item.Num;
                    }
                    else
                    {
                        size.Inventory += item.Num;
                        g.Sales -= item.Num;
                    }
                }

                await _goodsSizeRepository.UpdateRangeAsync(goodsSize, UpdatingProps<GoodsSize>(x => x.Inventory));
                await _goodsRepository.UpdateRangeAsync(goods, UpdatingProps<Goods>(x => x.Sales));
            }

            if (input.Gift.Count() > 0)
            {
                var giftIds = input.Gift.Select(x => x.Id).ToList();
                var gifts = await _goodsGiftRepository.Where(x => giftIds.Contains(x.Id)).ToListAsync();
                foreach (var item in input.Gift)
                {
                    var gift = gifts.Find(x => x.Id == item.Id);
                    if (input.Type == 1)
                        gift.RemainderCount -= item.Num;
                    else
                        gift.RemainderCount += item.Num;
                }

                await _goodsGiftRepository.UpdateRangeAsync(gifts, UpdatingProps<GoodsGift>(x => x.RemainderCount));
            }
            return AppSrvResult();
        }

        /// <summary>
        /// 获取通排调补信息
        /// </summary>
        /// <param name="language"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<GroupedProductDto>>> GetGroupedProductInfor(string language)
        {
            bool isZh = language.Equals(LanguageConsts.ZH);
            //获取用户等级
            var userGradeResponse = await _userRpcService.GetUserGrade();
            if (!userGradeResponse.IsSuccessStatusCode)
                return Problem(HttpStatusCode.InternalServerError, "服务异常,获取用户信息失败");
            var usergrade = userGradeResponse.Content;

            var group = await _goodsGroupRepository.Where(x => x.Type == 3).OrderBy(x => x.Sort).ToListAsync();
            var groupIds = group.Select(x => x.Id).ToArray();
            var groupGoods = await _groupGoodsRepository.Where(x => groupIds.Contains(x.GroupID)).ToListAsync();
            var goodsIds = groupGoods.Select(x => x.GoodsID).Distinct().ToArray();
            var goodsinfor = await _goodsRepository.Where(x => goodsIds.Contains(x.Id) && x.State == 0 && (x.PutawayTime == null || x.PutawayTime < DateTime.Now) && (x.OffLoadingTime == null || x.OffLoadingTime > DateTime.Now) ).ToListAsync();
            var sizeInfor = await _goodsSizeRepository.Where(x => goodsIds.Contains(x.GoodsID) && x.IsDefalut == true && x.State == 0).ToListAsync();
            var sizeIds = sizeInfor.Select(x => x.Id).ToArray();
            var prices = await _goodsPriceRepository.Where(x => sizeIds.Contains(x.SizeID) && x.UserLevel == usergrade).ToListAsync();
            var gift = await _goodsGiftRepository.Where(x => sizeIds.Contains(x.ParentGoodsSizeId) && x.RemainderCount > 0 && x.IsDelete == false).ToListAsync();
            
            var giftSize = new List<GoodsSize>();
            var giftGoods = new List<Goods>();
            if (gift.Any())
            {
                var giftSizeIds = gift.Select(x => x.SizeId).ToArray();
                var giftGoodsIds = gift.Select(x => x.GoodsId).ToArray();
                giftSize = await _goodsSizeRepository.Where(x => giftSizeIds.Contains(x.Id)).ToListAsync();
                giftGoods = await _goodsRepository.Where(x => giftGoodsIds.Contains(x.Id)).ToListAsync();
            }
            var result = new List<GroupedProductDto>();
            foreach (var item in group)
            {
                var data = new GroupedProductDto() {
                    GroupName = isZh ? item.Name : item.UighurName,
                    Img = isZh ? item.Banner : item.UighurBanner,
                };

                data.GoodsInfo = (from gg in groupGoods
                 join g in goodsinfor on gg.GoodsID equals g.Id
                 join s in sizeInfor on g.Id equals s.GoodsID
                 join p in prices on s.Id equals p.SizeID
                 where gg.GroupID == item.Id
                 select new ProductListWithGiftDto
                 {
                     Id = g.Id,
                     Name = isZh ? g.Name : g.UighurName,
                     SizeId = s.Id,
                     SizeName = isZh ? s.Name : s.UighurName,
                     IsThirdParties = g.IsThirdParties,
                     IsForeign = g.IsForeign,
                     OriginalPrice = s.Price,
                     SurfacePlot = s.Thumbnail,
                     Tag = JsonSerializer.Deserialize<String[]>(isZh ? g.Tag : g.UighurTag),
                     CurrentPrice = p.Price,
                 }).ToList();
                data.GoodsInfo.ForEach(x =>
                {
                    x.Gift = new List<ProductGiftDto>();
                    var gf = gift.FindAll(c => c.ParentGoodsSizeId == x.SizeId);
                    foreach (var g in gf)
                    {
                        var gg = giftGoods.First(c => c.Id == g.GoodsId);
                        var gs = giftSize.First(c => c.Id == g.SizeId);
                        x.Gift.Add(new ProductGiftDto
                        {
                            Id = x.Id,
                            SizeId = gs.Id,
                            SizeName = isZh ? gs.Name : gs.UighurName,
                            GoodsId = g.Id,
                            GoodsName = isZh ? gg.Name : gg.UighurName,
                            Count = g.Count,
                            RemainderCount = g.RemainderCount,
                            IsSuperposition = g.IsSuperposition,
                            BuyCount = g.BuyCount,
                        });
                    }
                });
                result.Add(data);
            }

            return result;
        }

        /// <summary>
        /// 添加评论
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<bool>> ReviewAdd(ProductReviewAddDto input)
        {
            return (await _goodsReviewRepository.InsertAsync(new GoodsReview() { 
                Id = IdGenerater.GetNextId(),
                UserId = input.UserId,
                Content = input.Content,
                GoodGrade = input.GoodGrade,
                Image = input.Image,
                GoodsId=input.GoodsId,
                OrderId = input.OrderId,
                Serve = input.Serve,
                Service = input.Service,
                Logistics = input.Logistics,
                Video = input.Video,
                CreateTime = DateTime.Now
            })) > 0;
        }

        /// <summary>
        /// 获取评论数量
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<ProductReviewQuantityDto>> GetProductReviewNum(long input)
        {
            var result = new ProductReviewQuantityDto();
            result.Total = await _goodsReviewRepository.CountAsync(x => x.GoodsId == input);
            result.GoodNum = await _goodsReviewRepository.CountAsync(x => x.GoodsId == input && x.GoodGrade == 1);
            result.CommonlyNum = await _goodsReviewRepository.CountAsync(x => x.GoodsId == input && x.GoodGrade == 2);
            result.BadNum = await _goodsReviewRepository.CountAsync(x => x.GoodsId == input && x.GoodGrade == 3);
            return result;
        }

        /// <summary>
        /// 获取评论列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<PageModelDto<ProductReviewListDto>>> GetProductReview(ProductReviewPagedSearcheDto input)
        {
            var expression = ExpressionCreator.New<GoodsReview>()
                .And(x => x.GoodsId == input.Id)
                .AndIf(input.Grade > 0, x => x.GoodGrade == input.Grade);
            var count = await _goodsReviewRepository.CountAsync(expression);
            var reviws = await _goodsReviewRepository.Where(expression)
                .Skip(input.PageSize * (input.PageIndex - 1))
                .Take(input.PageSize)
                .ToListAsync();
            var userIds = reviws.Select(x => x.UserId).Distinct().ToList();

            var userResponse = await _userRpcService.GetUserNameAndHead(userIds);
            if (!userResponse.IsSuccessStatusCode)
                return Problem(HttpStatusCode.InternalServerError, "服务异常");
            var user = userResponse.Content;

            var data = new List<ProductReviewListDto>();
            foreach (var item in reviws)
            {
                data.Add(new ProductReviewListDto
                {
                    Id = item.Id,
                    CommentTime = TimeHelper.GetTimeSpanStr(item.CreateTime),
                    Content = item.Content,
                    Video = JsonSerializer.Deserialize<string[]>(item.Video),
                    Image = JsonSerializer.Deserialize<string[]>(item.Image),
                    HeadUrl = user.FirstOrDefault(x => x.Id == item.UserId)?.Head,
                    UserName = user.FirstOrDefault(x => x.Id == item.UserId)?.Name,
                });
            }

            return new PageModelDto<ProductReviewListDto>(input, data, count);
        }

        /// <summary>
        /// 评论回复
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult> ReviewReply(long userId, ProductReviewReplyAddDto input)
        {
            await _goodsReviewReplyRepository.InsertAsync(new GoodsReviewReply()
            {
                Id = IdGenerater.GetNextId(),
                UserId = userId,
                ReviewId = input.ReviewId,
                Content = input.Content,                
                CreateTime = DateTime.Now
            });
            return AppSrvResult();
        }

        /// <summary>
        /// 获取评论详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<ProductReviewDetailDto>> GetReviewDetail(long input)
        {
     
            var review = await _goodsReviewRepository.FindAsync(input);
            if (review == null)
                return Problem(null, "参数错误");
            var reply = await _goodsReviewReplyRepository.Where(x => x.ReviewId == review.Id).ToListAsync();
            var userId = new List<long>
            {
                review.UserId
            };
            userId.AddRange(reply.Select(x => x.UserId).ToArray());
            userId.Distinct();

            var userResponse = await _userRpcService.GetUserNameAndHead(userId);
            if (!userResponse.IsSuccessStatusCode)
                return Problem(HttpStatusCode.InternalServerError, "服务异常");
            var user = userResponse.Content;

            var result = new ProductReviewDetailDto()
            {
                Id = review.Id,
                CommentTime = review.CreateTime,
                Content = review.Content,
                Image = JsonSerializer.Deserialize<string[]>(review.Image),
                Video = JsonSerializer.Deserialize<string[]>(review.Video),
                HeadUrl = user.FirstOrDefault(x => x.Id == review.UserId)?.Head,
                UserName = user.FirstOrDefault(x => x.Id == review.UserId)?.Name,
                Reply = new List<ProductReviewReplyDto>()
            };
            foreach (var item in reply)
            {
                result.Reply.Add(new ProductReviewReplyDto
                { 
                    Content = item.Content,
                    CommentTime = TimeHelper.GetTimeSpanStr(item.CreateTime),
                    HeadUrl = user.FirstOrDefault(x => x.Id == item.UserId)?.Head,
                    UserName = user.FirstOrDefault(x => x.Id == item.UserId)?.Name
                });
            }

            return result;
        }

        /// <summary>
        /// 创建商品code
        /// </summary>
        /// <param name="top"></param>
        /// <returns></returns>
        private string CreateNo(string top = "GG")
        {
            Random random = new Random();
            string strRandom = random.Next(10000, 99999).ToString();
            string code = $"{top}{DateTime.Now.ToString("yyyyMMddHHmmssffff")}{strRandom}";
            return code;
        }
    }
}
